package cbr.resilienceManager.qmul.gemom;

import inl.resilienceManager.qmul.gemom.TableSaver;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Hashtable;

import resilienceManager.qmul.gemom.Gbroker;

/**
 * The Case based resoning logic 
 * 
 * COPYRIGHT DISCLAIMER
 * Synopsis: All the source codes presented in this document are intellectual
 * properties of Queen Mary, University of London.
 * 
 * @year 2010
 * @author Peng Jiang, John Bigham, Jiayi Wu Jinfu Wang------------QMUL
 * @version 1.0 
 */

public class CbrOnUpdate {
//	if name:value indicate broker failures
// load the broker IDs in db


//	db settings
	private final static String driver= "com.mysql.jdbc.Driver";
	// the url of database
	private final static String url="jdbc:mysql://127.0.0.1:3306/test";
	// the username
	private final static String user="root";
	// the password
	private final static String password = "admin"; 
	// the table name used for the variance
	private final static String tablename = "varTable";
//	table of mean rates
	private final static String ratestablename = "ratestable";
//	solution table
	private final static String soltabname = "soltab";
	static ArrayList<String> brokers;  

//  flag if the solkey is in casebase	
	boolean flag = true;
	static String solkey="";
	static String inikey="";
	String[] livebrokers = null;
	String[] deadbrokers = null;
	int[] allBrokerIDs = TableSaver.getAllBrokerIDs();
	int[] livebrokerIDs = allBrokerIDs;
	int[] deadbrokerIDs = null;
	HashMap<String, String> idip = TableSaver.getMapIDIP();
	HashMap<String, String> ipid = TableSaver.getMapIPID();
	HashMap<String, String> idns = TableSaver.getMapIDNS();
	HashMap<String, String> itemns = TableSaver.getMapItemNS();
	public CbrOnUpdate(){
		
		livebrokers = new String[]{"192.168.1.100","192.168.1.102","192.168.1.103","192.168.1.104"}; 
		deadbrokers = new String[]{"192.168.1.101"};
		for (int i=0; i<allBrokerIDs.length; i++){
			inikey=inikey+1;
		}
//		HashMap<String, String> idip = TableSaver.getMapIDIP();
//		HashMap<String, String> idns = TableSaver.getMapIDNS();
//		HashMap<String, String> itemns = TableSaver.getMapItemNS();
		
//		brokers=new ArrayList<String>();
//		solLoader();
//		outputSol(Integer.valueOf(getString(solkey)));
	}
	

/*	
		hashtable
		get deadlist String[]
		get livelist
		get brokerid
		update vector
		
		send request
		
		for (ip : deadlist)
			select brokerid from  brokers where ip=
		getSolkey
		select items from sol where id=solkey
		
		if solkey is all 1
		primary = get items from item0
		if solkey is not all 1
		primary
		mirror=
		put in hashtable
		
		This method return a boolean value signifying if a query is
		valid and solution subsequently provided
	*/
		public boolean updateState(Hashtable GEMOMHashtable){
			String sk = null; 
			
			if (GEMOMHashtable.get("Flag")!=null && GEMOMHashtable.get("Flag").toString().equals("Initialize")){
				sk=inikey;
				
				
			}
			else if (GEMOMHashtable.contains("livebrokers")&&GEMOMHashtable.contains("deadbrokerds")){
				livebrokers = GEMOMHashtable.get("livebrokers").toString().split(",");
				deadbrokers = GEMOMHashtable.get("deadbrokerds").toString().split(",");
				deadbrokerIDs = getBrokerIDs(deadbrokers);
				livebrokerIDs = getBrokerIDs(livebrokers);
				sk = getSolkey(allBrokerIDs, deadbrokerIDs);
				 
			}
			
			else {
				// query message is either in a wrong format or corrupted, do 
				// not respnd with any solutions
				System.out.println("message format error");
				return false;
			}
			
			if(sk.equals(solkey)){
				System.out.println("brokers' state has not changed");
			}
			
			solkey = sk;
			//updateOM(sk); 
			return true;
		}
		 
		public int[] getBrokerIDs(String[] brokers){
			int[] ids = new int[brokers.length];
			for (int i = 0; i<brokers.length; i++){
				ids[i]=Integer.valueOf(ipid.get(brokers[i]));
			}
			return ids;
		}


//	//	brokers which become live or dead
//	public static String onUpdate(int[] id, int state[], int[] solkey){
////		detected broker failures and restore:
////		list of broker IDs, and list of their status - 1 for alive, 0 for dead
//		boolean changed = false;
//		for (int i=0; i< id.length; i++){
//			int b = brokers.indexOf(id[i]);
//			if (solkey[b]!=state[i]){
//				solkey[b]=state[i];
//				changed= true;
//			}
//		}
//		
//		if(changed){
//			return outputSol(Integer.valueOf(getString(solkey)));
//		} 	else{
//			return "";
//		}
//	}
	
//	send command to OM
	public Hashtable<String, String> updateOM(String sk){
		Hashtable<String, String> solution = getSol(sk);
		publishSol(solution);
		return solution;
	}
	
	// This method is left blank for possible future use. In current version the 
	// solution is passed on to a publisher through the updateOM() method
	public void publishSol(Hashtable solution){
		
	}
 
	public  Hashtable<String, String> getSol(String id){
			Hashtable<String, String> output = new Hashtable<String, String>();
			String s = "";
			try { 
				// load the driver
				Class.forName(driver); 
	
				// connect with database
				Connection conn = DriverManager.getConnection(url, user, password); 
	
				if(!conn.isClosed()) 
				{
					//System.out.println("Succeeded connecting to the Database!");	
				}
	
				PreparedStatement statement = conn.prepareStatement(
		        "SELECT * FROM "+soltabname+  " WHERE id = ? ");
				statement.setString(1,	id);
				ResultSet rs = statement.executeQuery();
	//			int row=0;
	
				ResultSetMetaData rsmd = rs.getMetaData();
				int noOfColumns = rsmd.getColumnCount();
				if(id.equals(inikey)){
					while(rs.next()){
						for (int brokerid:livebrokerIDs){
							//						"ip"="ns1,ns2"
							String items = rs.getString("b"+brokerid);
							String ns="";
							if (items!=null && items.length()!=0){
								String[] itemsa = items.split("-");
								//							items number array - get namespace IDs - get namespace names
								for (String i : itemsa){
									String[] nsida =itemns.get(""+(Integer.parseInt(i)-1)).split(",");
									for (String ii : nsida){
										ns = ns + idns.get(ii)+",";
									}
								}
								output.put(idip.get(""+brokerid)+"primay",ns);
							}

							else{
								output.put(idip.get(""+brokerid)+"primary", "");
							}
						}
					}
				}	
				else {
					while(rs.next()){
						for (int brokerid:livebrokerIDs){
							//						"ip"="ns1,ns2"
							String items = rs.getString("b"+brokerid);
							String ns="";
							if (items!=null && items.length()!=0){
								String[] itemsa = items.split("-");
								//							items number array - get namespace IDs - get namespace names
								for (String i : itemsa){
									String[] nsida =itemns.get(""+(Integer.parseInt(i)-1)).split(",");
									for (String ii : nsida){
										ns = ns + idns.get(ii)+",";
									}
								}
								output.put(idip.get(""+brokerid)+"mirror",ns);
							}

							else{
								output.put(idip.get(""+brokerid)+"mirror", "");
							}
						}
					}
				}
//					for(int i=2; i<noOfColumns+1; i++){
//						String a=rs.getString(i);
//						if (a!="" && a!=null && a.length()!=0){
//							s=s+"BrokerID: "+ brokers.get(i-2) + ", Items: " + a + "; ";
//							System.out.println("BrokerID: "+ brokers.get(i-2) + ", Items: " + a);
//						}
//						
//					}
	
//				}
	
				conn.close(); 
				flag = true;
			} catch(Exception e) { 
				flag = false;
				e.printStackTrace(); 
				
			}
	
			return output;
	
		}


	public static String getSolkey(int[] allBrokerIDs,int[] deadBrokerIDs){
		int[] solkey = new int[allBrokerIDs.length];
		Arrays.fill(solkey, 1);
	
		for (int d: deadBrokerIDs){
			for (int i=0; i<allBrokerIDs.length; i++){
				if(allBrokerIDs[i]==d){
					solkey[i]=0;
				}
			}
		}
		String s= "";
		for (int i :solkey ){
			s=s+i;
		}
		return s;
	}


	public static void solLoader(int[] solkey){
		try { 
			// load the driver
			Class.forName(driver); 

			// connect with database
			Connection conn = DriverManager.getConnection(url, user, password); 

			if(!conn.isClosed()) 
			{
				//System.out.println("Succeeded connecting to the Database!");	
			}

			PreparedStatement statement = conn.prepareStatement(
	        "SELECT * FROM "+soltabname);
			ResultSet rs = statement.executeQuery();
			ResultSetMetaData rsmd = rs.getMetaData();
			int noOfColumns = rsmd.getColumnCount();
			
			solkey = new int[noOfColumns-1 ]; 
			Arrays.fill(solkey, 1);
			for(int i=2; i<noOfColumns+1; i++){
				brokers.add(rsmd.getColumnName(i));
			}
//			rsmd.getColumnName(i+2);
//			TODO ini brokers with columns of broker IDs
			
			conn.close(); 

		} catch(Exception e) { 

			e.printStackTrace(); 
		}
	}
	
	
	public static String outputSol(int id){
		String s = "";
		try { 
			// load the driver
			Class.forName(driver); 

			// connect with database
			Connection conn = DriverManager.getConnection(url, user, password); 

			if(!conn.isClosed()) 
			{
				//System.out.println("Succeeded connecting to the Database!");	
			}

			PreparedStatement statement = conn.prepareStatement(
	        "SELECT * FROM "+soltabname+  " WHERE id = ? ");
			statement.setInt(1,	id);
			ResultSet rs = statement.executeQuery();
//			int row=0;
			ResultSetMetaData rsmd = rs.getMetaData();
			int noOfColumns = rsmd.getColumnCount();
			while(rs.next()){

				for(int i=2; i<noOfColumns+1; i++){
					String a=rs.getString(i);
					if (a!="" && a!=null && a.length()!=0){
						s=s+"BrokerID: "+ brokers.get(i-2) + ", Items: " + a + "; ";
						System.out.println("BrokerID: "+ brokers.get(i-2) + ", Items: " + a);
					}
					
				}

			}

			conn.close(); 

		} catch(Exception e) { 

			e.printStackTrace(); 
		}

		return s;

	}
	
	public static String getString(int[] a){
		String s= "";
		for (int i :a ){
//			s=s+ String.valueOf(i);
			s=s+i;
		}
		return s;
	}
	
/**
	 * @param args
	 */
	public static void main(String[] args) {
		CbrOnUpdate cou = new CbrOnUpdate();
		cou.updateOM(inikey);
		String sk = getSolkey(TableSaver.getAllBrokerIDs(), TableSaver.getBrokerIDs(cou.deadbrokers));
//		String sk = getSolkey(TableSaver.getAllBrokerIDs(), TableSaver.getBrokerIDs(cou.deadbrokers));
//		HashMap<String, String> idip = TableSaver.getMapIDIP();
//		HashMap<String, String> idns = TableSaver.getMapIDNS();
//		HashMap<String, String> itemns = TableSaver.getMapItemNS();
		System.out.println();
//		outputSol(1111);
	}

	
}
